home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ALIAS.ZIP / ALIASC.C < prev    next >
C/C++ Source or Header  |  1996-04-09  |  33KB  |  1,355 lines

  1. /*
  2. Scaling, Rotation, Antialiasing prototyper.
  3.  
  4. This program was written by Lewis A. Sellers (Minimalist)
  5. of The Minimalist Group, and the MOSOCI Grail Project in
  6. 1995-1996 Anno Dominus.
  7.  
  8. While it is the result of several days of work on my part,
  9. fiddled with here and there over a few months as time permits,
  10. you can use it and the code involved if you wish as long as
  11. you include the standard greetings to me somewhere in your program,
  12. say in the credits.
  13.  
  14. This program is the primary C/ASM version for DOS 16-bit.  There is
  15. also a PASCAL version which has a little better comments in some
  16. places. There are even newer functions here in the primary C version
  17. however since I decided to reveal the code.
  18.  
  19. There is also a pure asm (TASM) version of this program which I am tweaking
  20. on as I gain experience with the floating-point op-codes.
  21.  
  22. You must supply a BMP filename as an argument such as:
  23. C:> ALIAS DEATH.BMP
  24. The BMP it uses must be a 320x200 256 color grayscale image.
  25.  
  26. Most of this was originally written with borland turbo c++ 3.0 simply because
  27. it was easy to do so. To get a speed increase I tried using Borland C++ 4.52
  28. which I bought a while back. Most of the new Borland stuff is much more
  29. complicated than needs be so I hadn't used it much, but I did get about an
  30. extra two FPS from the recompile.
  31.  
  32. This program is designed for at least the 486 processors. Preferably pentiums.
  33.  
  34. Probably it'll end up as some kind of tutorial one day.
  35.  
  36. --MIN (rhymes with NIN)
  37.  
  38.   "the me that you know is now made up of wires
  39.    and even when i'm right with you i'm so far away" --NIN
  40. */
  41.  
  42. //tell TASM we can use .386 op-codes
  43. #pragma inline
  44. asm .486
  45. asm .487 //there is no 487 FPU but it makes TASM happy :)
  46. #pragma option -wasm- //yes, i know there are op-codes the built-in assembler
  47.                       //doesn't understand. shut up about it.
  48.  
  49. //this tells the compiler to use the FPU. If you are using a processor
  50. //without a FPU then comment this out and recompile.
  51. //#pragma OPTION -f287
  52.  
  53. //large memory model
  54. //#pragma option -ml
  55.  
  56. //8k stack
  57. extern unsigned _stklen = 8192U;
  58.  
  59. //.h prototypes
  60. //unsigned long farcoreleft(void);
  61.  
  62. #include <malloc.h>
  63. #include <alloc.h>
  64. #include <stdio.h>
  65. #include <stdlib.h>
  66. #include <conio.h>
  67. #include <time.h>
  68. #include <dos.h>
  69. #include <math.h>
  70.  
  71. #define FALSE (1==0)
  72. #define TRUE  (1==1)
  73.  
  74. #define WIDTH      320
  75. #define HEIGHT     200
  76. #define SCREENSIZE WIDTH*HEIGHT
  77.  
  78. #define FAILURE 0
  79. #define SUCCESS 1
  80.  
  81. #ifdef __cplusplus
  82.     #define __CPPARGS ...
  83. #else
  84.     #define __CPPARGS
  85. #endif
  86.  
  87. typedef unsigned char byte;
  88. typedef unsigned int word;
  89. typedef unsigned long dword;
  90.  
  91. //.h prototypes
  92. //size_t stackavail(void);
  93.  
  94. //prototypes
  95. void change_timer(void);
  96. void restore_timer(void);
  97. void mode_graphics(void);
  98. void mode_text(void);
  99. int LoadTestImage(char *name);
  100. void setup_fps(void);
  101. void print_fps(long fps);
  102. void bilinear(void);
  103. void trilinear(void);
  104. void hyperlinear(void);
  105. void copycomposite(void);
  106. void clearcomposite(void);
  107. int lines(void);
  108.  
  109. //TIMER
  110. #define TIMERINTR 8
  111. #define PIT_FREQ  0x1234DDL
  112. #define frequency 100
  113. #define counter   PIT_FREQ/frequency
  114.  
  115. long BIOS_ticks;
  116. int second_ticks;
  117. int second_flag=FALSE;
  118.  
  119. void interrupt far (*BIOStimerhandler)(__CPPARGS);
  120.  
  121. void interrupt far timerhandler(__CPPARGS)
  122. {
  123.   BIOS_ticks+=counter;
  124.   second_ticks++;
  125.   if(BIOS_ticks>=0x10000L) {
  126.       BIOS_ticks=0L;
  127. //      asm pushf
  128. //      call BIOStimerhandler
  129. ////      (*BIOStimerhandler)(__CPPARGS);
  130.   }
  131.   if(second_ticks>=100) {
  132.       second_flag=TRUE;
  133.       second_ticks=0;
  134.   }
  135.   outportb(0x20,0x20);
  136. }
  137.  
  138. void change_timer()
  139. {
  140.   //initialize the tick counter to 0
  141.   BIOS_ticks=0L;
  142.   second_ticks=0;
  143.  
  144.   //swap out the BIOS handler for our own....
  145.   BIOStimerhandler=getvect(TIMERINTR);
  146.   setvect(TIMERINTR,timerhandler);
  147.  
  148.   //change the clock frequency to 100 per second
  149.   outportb(0x43,0x34);
  150.   outportb(0x40,(byte)(counter%256));
  151.   outportb(0x40,(byte)(counter/256));
  152. }
  153.  
  154. void restore_timer()
  155. {
  156.   //restore 18.2 frequency of PIT 0
  157.   outportb(0x43,0x34);
  158.   outportb(0x40,0);
  159.   outportb(0x40,0);
  160.  
  161.   //restore the BIOS tick handler
  162.   setvect(TIMERINTR,BIOStimerhandler);
  163. }
  164.  
  165.  
  166. //GRAPHICS
  167. #define PI 3.14159265359
  168.  
  169. //char far *base_screen=(char far *)MK_FP(0xA000,0);
  170. char far *texture;
  171. int far *y320;
  172. char far *composite;
  173.  
  174. void mode_graphics(void)
  175. {
  176.     asm mov ax,0x13 //to mode 13h
  177.     asm int 0x10
  178.     outportb(0x3c2,0xe3); //put it in square mode
  179. }
  180.  
  181.  
  182. void mode_text(void)
  183. {
  184.     asm mov ax,0x03 //back to text
  185.     asm int 0x10;
  186. }
  187.  
  188.  
  189. //load in a grayscale 320x200 BMP
  190. int LoadTestImage(char *name)
  191. {
  192.     FILE *bmp;
  193.     int n,x,y;
  194.     word psi;
  195.     word source=(HEIGHT-1)*WIDTH;
  196.     word destination=0;
  197.     byte far *palette;
  198.     byte far *thrash;
  199.  
  200.     bmp=fopen(name,"rb");
  201.     if(bmp==NULL) return FAILURE;
  202.     fseek(bmp,54,0);
  203.  
  204.     //from b-g-r-unused dword format to proper RGB 3byte.
  205.     palette=(byte *)farmalloc(1024L+16L);
  206.     if(palette==NULL) {
  207.         mode_text();
  208. //        printf("Not enough memory (%lu) for palette.\n",farcoreleft());
  209.         exit(FAILURE);
  210.     }
  211.     fread(palette,1024,1,bmp);
  212.     outportb(0x3c6,0xff);
  213.     outportb(0x3c8,0);
  214.     for(psi=0,n=0;n<=255;n++,psi+=4)
  215.     {
  216.         outportb(0x3c9,palette[psi+2]>>2);
  217.         outportb(0x3c9,palette[psi+1]>>2);
  218.         outportb(0x3c9,palette[psi]>>2);
  219.     }
  220.     farfree(palette);
  221.  
  222.     // thrash the dumb MS format...
  223.     thrash=(byte far *)farmalloc(320L*200L);
  224.     if(thrash==NULL) {
  225.         mode_text();
  226. //        printf("Not enough memory (%lu) for temporary bitmap thrashing area.\n",farcoreleft());
  227.         exit(FAILURE);
  228.     }
  229.     fread(thrash,320U*200U,1,bmp);
  230.     for(y=0;y<HEIGHT;y++)
  231.     {
  232.         for(x=0;x<WIDTH;x++) {
  233.             texture[destination+x]=thrash[source+x];
  234.         }
  235.         source-=WIDTH;
  236.         destination+=WIDTH;
  237.     }
  238.     farfree(thrash);
  239.  
  240.     fclose(bmp);
  241.     return SUCCESS;
  242. }
  243.  
  244.  
  245. //
  246. byte fpsset[8][24]={
  247.   " ###### ######   ####   ",
  248.   " #      #     # #    #  ",
  249.   " #      #     # #       ",
  250.   " #####  ######   ####   ",
  251.   " #      #            #  ",
  252.   " #      #            #  ",
  253.   " #      #       #    #  ",
  254.   " #      #        ####   "
  255. };
  256.  
  257. byte charset[10][8][8]={
  258.   //0
  259.  {"  ##### ",
  260.   " #     #",
  261.   " #     #",
  262.   " #     #",
  263.   " #     #",
  264.   " #     #",
  265.   "  ##### ",
  266.   "        "},
  267.   //1
  268.  {"     ## ",
  269.   "      # ",
  270.   "      # ",
  271.   "      # ",
  272.   "      # ",
  273.   "      # ",
  274.   "     ###",
  275.   "        "},
  276.   //2
  277.  {"   #### ",
  278.   "  #    #",
  279.   "       #",
  280.   "    ### ",
  281.   "   #    ",
  282.   "  #    #",
  283.   "  ##### ",
  284.   "        "},
  285.   //3
  286.  {"  ##### ",
  287.   " #     #",
  288.   "       #",
  289.   "   #### ",
  290.   "       #",
  291.   " #     #",
  292.   "  ##### ",
  293.   "        "},
  294.   //4
  295.  {"    ##  ",
  296.   "   # #  ",
  297.   "  #  #  ",
  298.   " ###### ",
  299.   "     #  ",
  300.   "     #  ",
  301.   "    ### ",
  302.   "        "},
  303.   //5
  304.  {" #######",
  305.   " #      ",
  306.   " #      ",
  307.   " ###### ",
  308.   "       #",
  309.   " #     #",
  310.   "  ##### ",
  311.   "        "},
  312.   //6
  313.  {"  ##### ",
  314.   " #      ",
  315.   " #      ",
  316.   " ###### ",
  317.   " #     #",
  318.   " #     #",
  319.   "  ##### ",
  320.   "        "},
  321.   //7
  322.  {"  ######",
  323.   " #     #",
  324.   "      # ",
  325.   "     #  ",
  326.   "    #   ",
  327.   "    #   ",
  328.   "    #   ",
  329.   "        "},
  330.   //8
  331.  {"  ##### ",
  332.   " #     #",
  333.   " #     #",
  334.   "  ##### ",
  335.   " #     #",
  336.   " #     #",
  337.   "  ##### ",
  338.   "        "},
  339.  
  340.   //9
  341.  {"  ##### ",
  342.   " #     #",
  343.   " #     #",
  344.   "  ######",
  345.   "       #",
  346.   "      # ",
  347.   "  ####  ",
  348.   "        "}
  349. };
  350.  
  351.  
  352.  
  353. //setup the fps counter...
  354. void setup_fps()
  355. {
  356.   int c,x,y;
  357.   byte far *vid=((byte far *)composite)+(8*320);
  358.  
  359.   //change the 0 to 9 charset from spaces and pound-signs
  360.   //into 0 and 255 (ie, black and white).
  361.   for(c=0;c<=9;c++)
  362.          for(y=0;y<=7;y++)
  363.       for(x=0;x<=7;x++)
  364.         if(charset[c][y][x]=='#')
  365.           charset[c][y][x]=255;
  366.         else
  367.           charset[c][y][x]=0;
  368.  
  369.   //draw a "FPS" right below where the fps will be.
  370.   //yes, it's slow C code, but here that's ok.
  371.   for(y=0;y<=7;y++)
  372.     for(x=0;x<=23;x++)
  373.       if(fpsset[y][x]=='#')
  374.         vid[y*320+x]=255;
  375.       else
  376.         vid[y*320+x]=0;
  377. }
  378.  
  379.  
  380. //draw a counter number at the top left of the graphics screen
  381. void print_fps(long fps)
  382. {
  383.   char s[10];
  384.   char *src;
  385.   word x_offset=0;
  386.   int c;
  387.  
  388.   sprintf(s,"%ld",fps);
  389.   src=s;
  390.   while((*src)!=NULL) {
  391.     c=(*src)-'0';
  392.     asm {
  393.       les di,composite
  394.       add di,x_offset
  395.  
  396.       push ds
  397.       mov ax,c
  398.       mov si,offset charset
  399.       mov dx,seg charset
  400.       mov ds,dx
  401.       mov dx,(8*8)
  402.       mul dx
  403.       add si,ax
  404.  
  405.       mov cx,8
  406.     }
  407. yloop:
  408.          asm {
  409.       push di
  410.       movsw
  411.       movsw
  412.       movsw
  413.       movsw
  414.       pop di
  415.       add di,320
  416.       sub cx,1
  417.       jnz yloop
  418.       pop ds
  419.     }
  420.     x_offset+=8;
  421.     src++;
  422.   }
  423.  
  424.   //ok. we wrote out the digits. now cleanup anything left over from the
  425.   //last time on the right. we assume no more than 6 digits MAX.
  426.   asm {
  427.       cld
  428.  
  429.       mov bx,8*6
  430.       sub bx,x_offset
  431.       shr bx,1
  432.  
  433.       les di,composite
  434.       add di,x_offset
  435.  
  436.       sub ax,ax
  437.       mov cx,8
  438.   }
  439. cloop:
  440.   asm {
  441.       push cx
  442.       push di
  443.       mov cx,bx
  444.       rep stosw
  445.       pop di
  446.       pop cx
  447.       add di,WIDTH
  448.       sub cx,1
  449.       jnz cloop
  450.   }
  451. }
  452.  
  453.  
  454. //this is the fixed-point version of the scaling/rotation routine.
  455. //since we want maximum speed while still remaining in C parts of this
  456. //may be hard to read compared to the general rotate/scale routine.
  457. //It is similiar to the mathematical version except it uses 16.16
  458. //fixed-point and computes an initial texture vector then does something
  459. //similiar to a two-level line drawing routine, ok?
  460. //frankly, it's still slow as hell when compared to the full asm version.
  461. //hmm. Is it just C or Borland that is the problem? :)
  462. void FastRotateScale(float scale, float angle)
  463. {
  464.     long sinas=sin(-angle)*65536L*scale;
  465.     long cosas=cos(-angle)*65536L*scale;
  466.  
  467.     //x' = cos(-angle)+sin(-angle)
  468.     //y' = cos(-angle)-sin(-angle)
  469.     long xc=160L*65536L - (100L*(cosas+sinas));
  470.     long yc=100L*65536L - (100L*(cosas-sinas));
  471.  
  472.     char far *screen=(char far *)composite;
  473.     int x,y;
  474.  
  475.     register int tempx,tempy;
  476.  
  477.     for (y=0;y<HEIGHT;y++) //normally from 0 to 199
  478.     {
  479.         long xlong=xc,ylong=yc; //init x/ylong to topleft of square
  480.         for (x=60;x<60+HEIGHT;x++) //normally from 0 to 319
  481.         {
  482.             tempx=(int)(xlong>>16);
  483.             tempy=(int)(ylong>>16);
  484.  
  485.             if( (tempx<0) || //clip
  486.                 (tempx>=WIDTH) ||
  487.                 (tempy<0) ||
  488.                 (tempy>=HEIGHT) )
  489.                 screen[x]=0; //clip to black
  490.             else
  491.                 screen[x]=texture[tempx+y320[tempy]]; //draw texel
  492.             //this also happens to be horrible mangled by borland
  493.             //and produces some very fat slow code.
  494.  
  495.             xlong+=cosas;ylong-=sinas;
  496.         }
  497.         screen+=WIDTH;
  498.         xc+=sinas;yc+=cosas;
  499.     }
  500. }
  501.  
  502.  
  503. //this is the revised floating-point version of the scaling/rotation routine.
  504. //now that I finally have a cpu that actually supports FPU op-code
  505. //(from a 486sx25 to a 486dx4-100) thought I'd try them out.
  506. //note that unlike the pure mathematical version, we compute the vector
  507. //of rotation just once at the beginning of the function.
  508. void RotateScale(float scale, //the scaling factor
  509.             float angle) //the rotation angle
  510. {
  511.     #define x_offset 60
  512.     #define y_offset 0
  513.     #define x_window 200
  514.     #define y_window 200
  515.     #define x_center WIDTH/2
  516.     #define y_center HEIGHT/2
  517.  
  518.     float sinas=sin(-angle)*scale;
  519.     float cosas=cos(-angle)*scale;
  520.  
  521.     //x' = cos(-angle)+sin(-angle)
  522.     //y' = cos(-angle)-sin(-angle)
  523.     float xc=x_center - ((x_window>>1)*(cosas+sinas));
  524.     float yc=y_center - ((y_window>>1)*(cosas-sinas));
  525.  
  526.     float tx, ty;
  527.     int x,y;
  528.     //actually to composite buffer and not to screen...
  529.     //but it can be changed easily.
  530.     char far *screen=composite+x_offset+y_offset*WIDTH;
  531.     for (y=0;y<y_window;y++)
  532.     {
  533.         tx=xc;
  534.         ty=yc;
  535.         for (x=0;x<x_window;x++)
  536.         {
  537.             if( (tx<0.0) ||
  538.                 (tx>=(float)WIDTH) ||
  539.                 (ty<0.0) ||
  540.                 (ty>=(float)HEIGHT) )
  541.                 screen[x]=0;
  542.             else
  543.                 screen[x]=texture[(int)(tx)+y320[(int)(ty)]];
  544.  
  545.             tx+=cosas;
  546.             ty-=sinas;
  547.         }
  548.         screen+=WIDTH;
  549.         xc+=sinas;
  550.         yc+=cosas;
  551.     }
  552. }
  553.  
  554.  
  555.  
  556. //This is the pure mathematical version of rotation and scaling.
  557. //It is naturally slow since it has not be optimized to take advantage
  558. //of the way computers currently operate. Nevertheless it can help
  559. //some of you understand what is going on in the other routines.
  560. //
  561. //"How slow can we go?"
  562. void MathematicalRotateScale(float scale, float angle)
  563. {
  564.     #define x_LEFT   0
  565.     #define x_RIGHT  200
  566.     #define y_TOP    0
  567.     #define y_BOTTOM 200
  568.  
  569.     #define x_offset 60
  570.     #define y_offset 0
  571.  
  572.     //precompute the cosine and sine values used to speed things up
  573.     float cosas=cos(angle)*scale;
  574.     float sinas=sin(angle)*scale;
  575.  
  576.     float xc, yc;
  577.     float tx, ty;
  578.  
  579.     int x,y;
  580.  
  581.     char far *screen;
  582.  
  583.     for (y=y_TOP;y<y_BOTTOM;y++)
  584.     {
  585.         for (x=x_LEFT;x<x_RIGHT;x++)
  586.         {
  587.             //compute the center of the texture bitmap
  588.             xc=(float)(x-100);
  589.             yc=(float)(y-100);
  590.  
  591.             //compute the translation of x and y into texture map
  592.             //x' = x*cos(angle) - y*sin(angle)
  593.             //y' = x*sin(angle) + y*cos(angle)
  594.             tx=( (xc * cosas) - (yc * sinas) ) + 160.0;
  595.             ty=( (xc * sinas) + (yc * cosas) ) + 100.0;
  596.  
  597.             //compute the pixel on the composite screen buffer to draw to
  598.             screen=composite+((x+x_offset)+(y+y_offset)*WIDTH);
  599.  
  600.             //clip to black any texels that fall off of our 320x200 map
  601.             if( (tx<0.0) ||
  602.                 (tx>=(float)WIDTH) ||
  603.                 (ty<0.0) ||
  604.                 (ty>=(float)HEIGHT) )
  605.                 *screen=0; //clipped to black
  606.             else
  607.                 *screen=texture[ (int)(tx) + ( (int)(ty)*320) ]; //texel
  608.         }
  609.     }
  610. }
  611.  
  612.  
  613. //16-bit code...um, sucks. You knew that already didn't you?
  614. //good.
  615. //Anyway, even with the added overhead of the protection mechanisms this would
  616. //be faster in protected mode.
  617. //ES:DI always points to the composite buffer, while FS:BX points to the texture
  618. #pragma option -wasm-
  619. long fixedconst=65536L;
  620. void TASMFixedRotateScale(float scale, float angle)
  621. {
  622.     #define x_offset 60
  623.     #define y_offset 0
  624.  
  625.     long sinas, cosas;
  626.     long xc, yc;
  627.     long xlong, ylong;
  628.     int y;
  629.  
  630.     asm {
  631.         //ok. these are precalculates requiring an FPU. An integrated 387 FPU
  632.         //in fact. The results will be... unfortunate on anything earlier.
  633.  
  634.         // sinas=sin(angle)*scale;
  635.         fld     dword ptr [angle] //st(0)
  636.         fchs //-angle
  637.         fsin //st(0)
  638.         fmul    dword ptr [scale] //st(0)=st(1)*st(0) ;pop;
  639.         fimul   dword ptr [fixedconst] //st(0)= dword 65536 * st(0)
  640.         fistp   dword ptr [sinas] //sinas=(long)st(0); pop;
  641.  
  642.         // cosas=cos(angle)*scale;
  643.         fld     dword ptr [angle]
  644.         fchs
  645.         fcos
  646.         fmul    dword ptr [scale]
  647.         fimul   dword ptr [fixedconst]
  648.         fistp   dword ptr [cosas]
  649.  
  650.         // xc=160*65536 - (100*(cosas+sinas));
  651.         mov ecx,160*65536
  652.         mov eax,cosas
  653.         mov edx,100
  654.         add eax,sinas
  655.         mul edx
  656.         sub ecx,eax
  657.         mov [xc],ecx //opt me
  658.  
  659.         // yc=100*65536 - (100*(cosas-sinas));
  660.         mov ecx,100*65536
  661.         mov eax,cosas
  662.         mov edx,100
  663.         sub eax,sinas
  664.         mul edx
  665.         sub ecx,eax
  666.         mov [yc],ecx //opt me
  667.  
  668.         //INITs
  669.         les     di, composite
  670.         lfs     bx, texture
  671.         add     di, x_offset
  672.  
  673.         // for (y=0;y<HEIGHT;y++) //normally from 0 to 199
  674.         mov     word ptr [y],0
  675.     }
  676. yloop: asm {
  677.         // xlong=xc,ylong=yc; //init x/ylong to topleft of square
  678.         mov     eax,[xc]
  679.         mov     edx,[yc]
  680.         mov     [xlong],eax
  681.         mov     [ylong],edx
  682.  
  683. //////////////////START OF X LOOP
  684.         mov cx,WIDTH-x_offset*2 //width of 200 pixels
  685.     }
  686. xloop: asm {
  687.         mov     dx, word ptr [ylong+2] //tempy=ylong>>16
  688.         mov     si, word ptr [xlong+2] //tempx=xlong>>16
  689.         mov     ax,dx //pipeline for the src=x+y*320 below. good on pentium?
  690.  
  691.         //CLIPPING SECTION
  692.         or      si,si //tempx<0?
  693.         jl      short clip
  694.         cmp     si,WIDTH //tempx>=320?
  695.         jge     short clip
  696.         or      dx,dx //tempy<0?
  697.         jl      short clip
  698.         cmp     dx,HEIGHT //tempy>=200?
  699.         jl      short noclip
  700.     }
  701. clip: asm {
  702.         mov     byte ptr es:[di],0
  703.         jmp     short doneclipping
  704.     }
  705. noclip: asm {
  706.         //compute x,y position into texture. si = x_offset + x + y*320
  707.         //mov ax,dx //pipelined away
  708.         shl     dx,8 //2c
  709.         shl     ax,6 //2c
  710.         add     si,dx //1c
  711.         add     si,ax //1c
  712.  
  713.         mov     al,byte ptr fs:[si+bx] //1c+1c get texel
  714.         mov     byte ptr es:[di],al //draw texel
  715.     }
  716. doneclipping: asm {
  717.                   //xlong+=yscale; ylong-=sinas
  718.         mov     edx, [sinas]
  719.         mov     eax, [cosas]
  720.         sub     [ylong],edx
  721.         add     [xlong],eax
  722.  
  723.         inc     di //screen++;
  724.  
  725.         sub     cx,1 //reversed x++
  726.         jnz     short xloop //loop x?
  727.         ////////////////
  728.  
  729.         //xc+=sinas; yc+=cosas
  730.         mov     eax,[sinas]
  731.         mov     edx,[cosas]
  732.         add     [xc],eax
  733.         add     [yc],edx
  734.  
  735.         inc     word ptr [y] //y++
  736.  
  737.         add di,x_offset*2 //add to get next y line
  738.  
  739.         //loop y?
  740.         cmp     word ptr [y],HEIGHT
  741.         jge     short endall
  742.         jmp     yloop
  743.     }
  744. endall: asm {
  745.     }
  746.     return;
  747. }
  748.  
  749.  
  750. //................ ignore. under construction.
  751. float widthconst=160.0;
  752. float heightconst=100.0;
  753. void TASMFloatingRotateScale(float scale, float angle)
  754. {
  755.     #define x_LEFT   0
  756.     #define x_RIGHT  200
  757.     #define y_TOP    0
  758.     #define y_BOTTOM 200
  759.  
  760.     #define x_offset 60
  761.     #define y_offset 0
  762.  
  763.     float cosas; //cos(angle)*scale;
  764.     float sinas; //sin(angle)*scale;
  765.  
  766.     int y;
  767.  
  768.     int tx,ty;
  769.     int xc,yc;
  770.  
  771.     asm {
  772.         //ok. these are precalculates requiring an FPU. An integrated 387 FPU
  773.         //in fact. The results will be... unfortunate on anything earlier.
  774.  
  775.         // sinas=sin(angle)*scale;
  776.         fld  dword ptr [angle] //st(0)
  777.         fsin //st(0)
  778.         fmul dword ptr [scale] //st(0)=st(1)*st(0) ;pop;
  779.         fstp dword ptr [sinas] //sinas=(long)st(0); pop;
  780.  
  781.         // cosas=cos(angle)*scale;
  782.         fld        dword ptr [angle]
  783.         fcos
  784.         fmul dword ptr [scale]
  785.         fstp dword ptr [cosas]
  786.     }
  787.  
  788.     asm { //INITs
  789.         les     di, composite
  790.         add     di, x_offset
  791.         lfs     bx, texture
  792.  
  793.         //
  794.         mov     word ptr [yc],y_TOP-100 //yc=(float)(y-100);
  795.         mov     word ptr [xc],x_LEFT-100 //xc=(float)(x-100);
  796.  
  797.         //center of the texture bitmap, y
  798.         fild    word ptr [yc] //st(1)
  799.         fild    word ptr [xc] //st(0)
  800.  
  801.         mov     word ptr [y],y_TOP //start of y loop
  802.     }
  803. yloop: asm {
  804.         //center of the texture bitmap, x
  805.         ffree   st(0)
  806.         fincstp
  807.         fild    word ptr [xc] //st(0)
  808.  
  809.         mov     cx,WIDTH-x_offset*2 //start of x loop
  810.     }
  811. xloop: asm {
  812.         //compute the translation of x and y into texture map
  813.         //x' = x*cos(angle) - y*sin(angle)
  814.         //y' = x*sin(angle) + y*cos(angle)
  815.  
  816.         //tx=( (xc * cosas) - (yc * sinas) ) + 160.0;
  817.         fld   dword ptr [cosas]
  818.         fmul  st,st(1) //xc*cosas
  819.  
  820.         fld   dword ptr [sinas]
  821.         fmul  st,st(3) //yc*sinas
  822.  
  823.         fsubp st(1),st
  824.         fadd  dword ptr [widthconst]
  825.         fistp word ptr [tx]
  826.  
  827.         fwait
  828.         mov   si,[tx] //pick up tx.
  829.  
  830.         //ty=( (xc * sinas) + (yc * cosas) ) + 100.0;
  831.         fld   dword ptr [cosas]
  832.         fmul  st,st(2) //yc*cosas
  833.  
  834.         fld   dword ptr [sinas]
  835.         fmul  st,st(2) //xc*sinas
  836.  
  837.         faddp st(1),st
  838.         fadd  dword ptr [heightconst]
  839.         fistp word ptr [ty]
  840.  
  841. //CLIPPING SECTION
  842.         or    si,si //tempx<0?
  843.         jl    short clip
  844.  
  845.         fwait
  846.         mov   dx,[ty] //get ty. hope it's ready by now....
  847.  
  848.         cmp   si,WIDTH //tempx>=320?
  849.         mov   ax,dx //pipelined code snuck into if branch....
  850.         jge   short clip
  851.  
  852.         or    dx,dx //tempy<0?
  853.         jl    short clip
  854.  
  855.         cmp   dx,HEIGHT //tempy>=200?
  856.         jl    short noclip
  857.     }
  858. clip: asm {
  859.         mov   byte ptr es:[di],0
  860.         jmp   short doneclipping
  861.     }
  862. noclip: asm {
  863.         //compute x,y position into texture. si = x_offset + x + y*320
  864.         //mov ax,dx //pipelined away
  865.         shl   dx,8 //2c
  866.         shl   ax,6 //2c
  867.         add   si,dx //1c
  868.         add   si,ax //1c
  869.  
  870.         mov   al,byte ptr fs:[si+bx] //1c+1c get texel
  871.         mov   byte ptr es:[di],al //draw texel
  872.     }
  873. doneclipping: asm {
  874.         inc   di //screen++
  875.  
  876.         fld1  //inc xc
  877.         faddp st(1),st
  878.  
  879.         sub   cx,1
  880.         jnz   short xloop
  881.  
  882.         fld1  //inc yc
  883.         faddp st(2),st
  884.  
  885.         add   di,x_offset*2 //screen+=60*2
  886.  
  887.         inc   word ptr [y] //y++
  888.         cmp   word ptr [y],y_BOTTOM //loop y?
  889.         jge   short endall
  890.         jmp   yloop
  891.     }
  892. endall: asm {
  893.         //
  894.         ffree st(1)
  895.         ffree st(0)
  896.     }
  897.     return;
  898. }
  899.  
  900.  
  901. //post bilinear antialiasing
  902. void bilinear()
  903. {
  904.     asm {
  905.          push ds
  906.          lds di,composite
  907.          add di,(WIDTH+1)+60
  908.          mov cx, (HEIGHT-2)
  909.     }
  910. yloop:
  911.     asm {
  912.          push cx
  913.          push di
  914.          mov cx, (WIDTH-2) - 60*2
  915.     }
  916. xloop:
  917.     asm {
  918.         sub ax,ax
  919.         sub bx,bx
  920.         mov al,[di-1]
  921.         add bx,ax
  922.         mov al,[di+1]
  923.         add bx,ax
  924.         mov al,[di-WIDTH]
  925.         add bx,ax
  926.         mov al,[di+WIDTH]
  927.         add bx,ax
  928.  
  929.         shr bx,2
  930.  
  931.         mov al,[di]
  932.         add bx,ax
  933.         shr bx,1
  934.  
  935.         mov [di],bl
  936.         inc di
  937.         sub cx,1
  938.         jnz xloop
  939.  
  940.         pop di
  941.         pop cx
  942.         add di,WIDTH
  943.         sub cx,1
  944.         jnz yloop
  945.         pop ds
  946.     }
  947. }
  948.  
  949.  
  950. //post trilinear antialiasing
  951. void trilinear()
  952. {
  953.     asm {
  954.         push ds
  955.         lds di,composite
  956.         add di,(WIDTH+1) + 60
  957.         mov cx, (HEIGHT-2)
  958.     }
  959. yloop:
  960.     asm {
  961.         push cx
  962.         push di
  963.         mov cx, (WIDTH-2) - 60*2
  964.     }
  965. xloop:
  966.     asm {
  967.         sub ax,ax
  968.         sub bx,bx
  969.         mov al,[di-1]
  970.         add bx,ax
  971.         mov al,[di+1]
  972.         add bx,ax
  973.         mov al,[di-WIDTH]
  974.         add bx,ax
  975.         mov al,[di+WIDTH]
  976.         add bx,ax
  977.  
  978.         mov al,[di-(WIDTH+1)]
  979.         add bx,ax
  980.         mov al,[di-(WIDTH-1)]
  981.         add bx,ax
  982.         mov al,[di+(WIDTH+1)]
  983.         add bx,ax
  984.         mov al,[di+(WIDTH-1)]
  985.         add bx,ax
  986.  
  987.         shr bx,3
  988.  
  989.         mov al,[di]
  990.         add bx,ax
  991.         shr bx,1
  992.  
  993.         mov [di],bl
  994.         inc di
  995.         sub cx,1
  996.         jnz xloop
  997.  
  998.         pop di
  999.         pop cx
  1000.         add di,WIDTH
  1001.         sub cx,1
  1002.         jnz yloop
  1003.         pop ds
  1004.     }
  1005. }
  1006.  
  1007.  
  1008. //post hyperlinear? antialiasing. This is just an experiment.
  1009. void hyperlinear()
  1010. {
  1011. mloop: asm {
  1012.         push ds
  1013.         lds di,composite
  1014.         add di,(WIDTH+1)+60
  1015.         mov cx,(HEIGHT-2)
  1016.     }
  1017. yloop:
  1018.     asm {
  1019.         push cx
  1020.         push di
  1021.         mov cx, (WIDTH-2) - 60*2
  1022.     }
  1023. xloop:
  1024.     asm {
  1025.         sub ax,ax
  1026.         sub dx,dx
  1027.         mov al,[di-1]
  1028.         add dx,ax
  1029.         mov al,[di+1]
  1030.         add dx,ax
  1031.         mov al,[di-WIDTH]
  1032.         add dx,ax
  1033.         mov al,[di+WIDTH]
  1034.         add dx,ax
  1035.  
  1036.         mov al,[di-(WIDTH+1)]
  1037.         add dx,ax
  1038.         mov al,[di-(WIDTH-1)]
  1039.         add dx,ax
  1040.         mov al,[di+(WIDTH+1)]
  1041.         add dx,ax
  1042.         mov al,[di+(WIDTH-1)]
  1043.         add dx,ax
  1044.  
  1045.         shr dx,3
  1046.  
  1047.         mov al,[di]
  1048.         add dx,ax
  1049.         shr dx,1
  1050.  
  1051.         mov [di-(WIDTH+1)],dl
  1052.         mov [di+(WIDTH+1)],dl
  1053.         mov [di-(WIDTH-1)],dl
  1054.         mov [di+(WIDTH-1)],dl
  1055.  
  1056.         inc di
  1057.         sub cx,1
  1058.         jnz xloop
  1059.  
  1060.         pop di
  1061.         pop cx
  1062.  
  1063.         add di,WIDTH
  1064.         sub cx,1
  1065.         jnz yloop
  1066.         pop ds
  1067.     }
  1068. }
  1069.  
  1070.  
  1071. void copycomposite()
  1072. {
  1073.     asm {
  1074.         mov ax,0xa000
  1075.         mov es,ax
  1076.         sub di,di
  1077.  
  1078.         push ds
  1079.         lds si,composite
  1080.         mov cx,SCREENSIZE/2
  1081.         cld
  1082.         rep movsw
  1083.         pop ds
  1084.     }
  1085. }
  1086.  
  1087.  
  1088. void clearcomposite()
  1089. {
  1090.     asm {
  1091.         les di,composite
  1092.         mov cx,SCREENSIZE/2
  1093.         sub ax,ax
  1094.         cld
  1095.         rep stosw
  1096.     }
  1097. }
  1098.  
  1099.  
  1100. /*
  1101. void test()
  1102. {
  1103.   int m1=7;
  1104.   int m2=3;
  1105.   float m3=2.5;
  1106.   int r1=0;
  1107.   float r2=0.0;
  1108.   float r3=0.0;
  1109.  
  1110.   asm {
  1111.                 fild word ptr m1
  1112.                 fimul word ptr m2
  1113.                 fist word ptr r1
  1114.                 fld m3
  1115.                 fmul
  1116.                 fst dword ptr r2
  1117.                 fstp qword ptr r3
  1118.   }
  1119.  
  1120.   printf("r1: %i\n",r1);
  1121.   printf("r2: %f\n",r2);
  1122.   printf("r3: %lf\n",r3);
  1123.  
  1124.   getch();
  1125. }
  1126. */
  1127.  
  1128.  
  1129. int main(int argc,char *argv[])
  1130. {
  1131.     float angle=PI/256.0;
  1132.     float angle_v=-PI/128.0;
  1133.     float scale=1.05;
  1134.     int n;
  1135.     int alias=0;
  1136.     int fpu=0;
  1137.     int key='~',key2=0; //so as not to trip up the arrow keys below
  1138.     long frames=0L;
  1139.  
  1140.     //inpho
  1141.     clrscr();
  1142.     printf("Scaling/Rotation/Antialiasing Prototyper by Minimalist 1995-1996.\n");
  1143.     printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
  1144.     #ifdef __TURBOC__
  1145.         printf("Compiler: Borland C++ version %x.%x. ",
  1146.         (__TURBOC__)/256,(__TURBOC__%256));
  1147.     #endif
  1148. //         printf("Memory:%lu. Stack:%u. ",farcoreleft(),stackavail());
  1149.     if(_8087)
  1150.         printf("FPU:%d87.",_8087);
  1151.     else
  1152.         printf("No FPU.");
  1153.     printf("\n\n");
  1154.  
  1155.     //you did specify a filename didn't you?
  1156.     if(argc!=2)
  1157.     {
  1158.         printf("Use: ALIASC 'filename.bmp'\n");
  1159.         printf("Such as ALIASC MISSCATG.BMP\n");
  1160.         return(FAILURE);
  1161.     }
  1162.  
  1163.     //the propaganda
  1164.     printf("This program requires at least a 486 with an integrated 387 grade FPU.\n");
  1165.     printf("The BMP must be 320x200 256 grayscale.\n\n");
  1166.  
  1167.     printf("You may use any of the following keys:\n");
  1168.     printf(" ESC will exit the program.\n");
  1169.  
  1170.     printf("Scaling and Rotation:\n");
  1171.     printf(" N   No floating-point, use fixed-point\n");
  1172.     printf(" F   Use floating-point\n");
  1173.     printf(" M   Use pure floating-point mathematical routine\n");
  1174.     printf(" X   Use TASM pipelined fixed-point\n");
  1175.     printf(" A   Use TASM pipelined floating-point\n");
  1176.  
  1177.     printf("Antialiasing:\n");
  1178.     printf(" 1   No antialiasing\n");
  1179.     printf(" 2   Post Bilinear antialiasing\n");
  1180.     printf(" 3   Post Trilinear antialiasing\n");
  1181.     printf(" 4   Post um.... post ghosting/antialiasing? :-)\n");
  1182.     printf("Use left/right arrows to change rotation.\n");
  1183.     printf("Zoom with the - + [ and ] keys. Use BACKSPACE to stop.\n\n");
  1184.  
  1185. //    test();
  1186.  
  1187.     //wait for windows to quit thrashing the hard drive...
  1188.     printf("Press any key to start...");
  1189.     while (!kbhit()); getch();
  1190.  
  1191.     //initialize our table of n*320
  1192.     y320=(int far *)farmalloc(2L*200L);
  1193.     if(y320==NULL) {
  1194.         mode_text();
  1195. //        printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
  1196.         exit(FAILURE);
  1197.     }
  1198.     for(n=0;n<HEIGHT;n++) y320[n]=n*WIDTH;
  1199.  
  1200.     //load our texture map
  1201.     texture=(char far *)farmalloc(320L*200L);
  1202.     if(texture==NULL) {
  1203.         mode_text();
  1204. //        printf("Not enough memory (%lu) for texture map.\n",farcoreleft());
  1205.         exit(FAILURE);
  1206.     }
  1207.  
  1208.     //switch to graphic mode 320x200 256 colors
  1209.     mode_graphics();
  1210.     if(LoadTestImage(argv[1])==FAILURE)
  1211.     {
  1212.         mode_text();
  1213.         printf("The file %s does not exist.\n",argv[1]);
  1214.         return(FAILURE);
  1215.     }
  1216.  
  1217.     //create a composite buffer (off-screen double buffer)
  1218.     composite=(char far *)farmalloc(320L*200L);
  1219.     if(composite==NULL) {
  1220.         mode_text();
  1221. //        printf("Not enough memory (%lu) for composite buffer.\n",farcoreleft());
  1222.         exit(FAILURE);
  1223.     }
  1224.  
  1225.     //set things up
  1226.     clearcomposite();
  1227.     setup_fps();
  1228.     change_timer();
  1229.  
  1230.     //the main loop
  1231.     while (key!=27) {
  1232.         if(kbhit()) {
  1233.             key=getch();
  1234.             switch (key) {
  1235.                 //internal testing frame for yazzie :)
  1236.                 case 'y':
  1237.                 case 'Y':
  1238.                     angle=PI/2.0;
  1239.                     angle_v=0.0;
  1240.                     scale=1.0;
  1241.                     break;
  1242.                 //and susy honey
  1243.                 case 'h':
  1244.                 case 'H':
  1245.                     angle+=PI/4.0;
  1246.                     angle_v=0.0;
  1247.                     break;
  1248.                 //and sissy
  1249.                 case 's':
  1250.                 case 'S':
  1251.                     angle-=PI/4.0;
  1252.                     angle_v=0.0;
  1253.                     break;
  1254.                 //and prissy
  1255.                 case 'z':
  1256.                 case 'Z':
  1257.                     scale=0.5;
  1258.                     angle=PI/2.0;
  1259.                     angle_v=-0.1;
  1260.                     break;
  1261.  
  1262.                 case 'n':
  1263.                 case 'N': fpu=0; break;
  1264.                 case 'f':
  1265.                 case 'F': fpu=1; break;
  1266.                 case 'm':
  1267.                 case 'M': fpu=2; break;
  1268.                 case 'a':
  1269.                 case 'A': fpu=3; break;
  1270.                 case 'x':
  1271.                 case 'X': fpu=4; break;
  1272.  
  1273.                 case '1': alias=1; break;
  1274.                 case '2': alias=2; break;
  1275.                 case '3': alias=3; break;
  1276.                 case '4': alias=4; break;
  1277.  
  1278.                 case '-': scale-=0.05; break;
  1279.                 case '=': scale+=0.05; break;
  1280.                 case '[': scale-=0.5; break;
  1281.                 case ']': scale+=0.5; break;
  1282.                 case 0:
  1283.                     key2=getch();
  1284.                     switch (key2) {
  1285.                         case 75: angle_v+=PI/128.0; break; //left arrow
  1286.                         case 77: angle_v-=PI/128.0; break; //right arrow
  1287.                     }
  1288.                     break;
  1289.             }
  1290.         }
  1291.  
  1292.         switch (fpu) {
  1293.             case 0: FastRotateScale(scale,angle); break;
  1294.             case 1: RotateScale(scale,angle); break;
  1295.             case 2: MathematicalRotateScale(scale,angle); break;
  1296.             case 3: TASMFixedRotateScale(scale,angle); break;
  1297.             case 4: TASMFloatingRotateScale(scale,angle); break;
  1298.         }
  1299.  
  1300.         switch (alias) {
  1301.           //case 1: do nothing....
  1302.             case 2: bilinear(); break;
  1303.             case 3: trilinear(); break;
  1304.             case 4: hyperlinear(); break;
  1305.         }
  1306.  
  1307.         copycomposite(); //show us the composite buffer!
  1308.  
  1309.         angle+=angle_v;
  1310.         if(angle>2*PI) angle-=2*PI; //bound our angle...
  1311.         if(angle<-2*PI) angle+=2*PI;
  1312.  
  1313.         //do the FPS calcing
  1314.         frames++;
  1315.         if(second_flag) { //been a second yet?
  1316.             second_flag=FALSE;
  1317.             print_fps(frames); //yes, so see how many frames we've done in that time.
  1318.             frames=0L; //and the frames
  1319.         }
  1320.     }
  1321.  
  1322.     //restore things to normal
  1323.     restore_timer();
  1324.     farfree(composite);
  1325.     farfree(texture);
  1326.     farfree(y320);
  1327.  
  1328.     //parting words....
  1329.     mode_text();
  1330.     printf("By Minimalist (Lewis A. Sellers) 1995-96. Part of the C/Pascal/Asm package.\n");
  1331.     printf("To contact, email: lsellers@1stresource.com (shortly to be lsellers@usit.net).\n");
  1332.     printf("or drop by http://www.dwc.edu/grail, site of Grail Operating System Project.\n\n");
  1333.  
  1334.     printf("#coders home page: http://www.realtime.net/~dlinvill/coders/index.html\n\n");
  1335.  
  1336.     printf("Psst. Testing out the original code or modification you did to it? Then press\n");
  1337.     printf("Z to set a standard scale and rotation factor. On a 486dx4 100mhz 256kb cache\n");
  1338.     printf("60ns DRAM, and an awful PCI Trio32 S3 graphics card, compiled with ");
  1339.     #ifdef __TURBOC__
  1340.         printf("Borland\nC++ version %x.%x.",
  1341.         (__TURBOC__)/256,(__TURBOC__%256));
  1342.     #endif
  1343.     printf("\n");
  1344.  
  1345.     printf("              M=~4.5fps F=~6fps X=~12fps N=~22fps A=~34fps\n\n");
  1346.  
  1347.     printf("         'It was men like me that built the bomb.' --paraphrased, T2\n\n");
  1348.  
  1349.     return(SUCCESS);
  1350. }
  1351.  
  1352.  
  1353. //cute trick of mine for single file programs
  1354. int lines() { return __LINE__+1; }
  1355.